test(dcs): finalize catch-up — EN translation, tier taxonomy, mt08/mt14 quarantine#24
Merged
Merged
Conversation
Since the dcs-bridge migration, only auto/auto-check scenarios have ever actually been run live — the 34 ia-tier scenarios (pilotPassive/pilotActive + 2 noPlayer outliers) and the 4 L6 manual sequences have never been executed. Scaffolds 8 tickets grouped by feature area, ordered fast/ foundational first and the heaviest AI battery (MT-07..16) and L6 checklist last, so each ticket is a standalone pilot session (~3.5h total, splittable). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CATCH-UP-PILOT-SCENARIOS ticket 01. F-047 used "CTLD Commands"/"Pack Vehicles" paths marked STALE in the i18n files since the menu rename; rewrote to the current tree (CTLD > FOBs List, CTLD > Crate Commands > Pack Equipt). Also added the setBranchEnabled(true) call the original never had -- the Pack Equipt node already exists disabled at slot-in (no packable vehicle nearby) and clearBranch alone doesn't re-enable it. Both F-046 and F-047 confirmed live (David, UH-1H). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…-scenario runner CATCH-UP-PILOT-SCENARIOS ticket 02, confirmed live (David, UH-1H): - Fix: CTLDTroopManager:refreshMenuSection always computed inAir live via _isInAir(unit), unlike CTLDCrateManager:refreshCrateFlightSection which accepts an overrideInAir param so onTakeoff/onLand can force the correct state immediately (S_EVENT_LAND fires before inAir()'s speed/AGL threshold settles). Found live: Parachute Troops stayed visible and Disembark Troops stayed hidden right after landing. refreshMenuSection now takes the same overrideInAir param, wired through onTakeoff/onLand/the flight-state poller. 3 new busted tests (menu_gating_spec.lua). - Fix: scenario_crate_menu_sol_vol_visual.lua's step C checklist expected "Pack Equipt VISIBLE" after step B already packed the vehicle -- a contradiction (nothing left to pack once packed). - Add tools/integration-runner/run_ia_scenario.py: interactive terminal runner for ia-tier pilotActive/pilotPassive scenarios that self-verify -- injects, mirrors in-game instructions to the terminal, polls to a verdict. Removes the AI middleman for the injection/polling loop; re-running the same command resets stuck state instead of requiring a DCS restart. - Bump HUMAN_TIMEOUT_S 300->3600s in the two L5 scenarios + the pilotActive template -- was a source of false FAILs, not a useful safety net, for a step meant to be answered at a real pilot's pace. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…e zone note CATCH-UP-PILOT-SCENARIOS ticket 03 prep: - run_ia_scenario.py now re-posts the full scenario source when it sees a RUNNING: step=N verdict (needed to advance the internal step machine), instead of only polling the result var (which only works for scenarios that resolve on their own via STARTED). run_scenarios.py --no-ai still correctly fails RUNNING headlessly (no human to do the physical part) -- this only changes the interactive runner, which has one. - scenarioTroopsFullCycle_v2.lua returned STARTED for incomplete steps instead of RUNNING: step=N like its sibling scenarios (jtac_crate_pack, feature_k_jtac_vehicle) -- inconsistent with the return contract and unusable by the new interactive runner. Fixed to return RUNNING. - Its header also claimed a "TRZ zone in mission" prerequisite that's stale: step 2 builds a CTLDTroopGroup directly in _inTransit and never calls embarkFromTroopZone or looks up a real zone. Verified live no such zone exists in Test_CTLDNEXT_01.miz, and none is needed. Comment fixed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…port in run_scenarios.py CATCH-UP-PILOT-SCENARIOS ticket 03. David's live run of scenario_jtac_crate_pack raised whether it belonged in ia at all -- checking the code confirmed all 4 ticket-03 scenarios never check real flight state or wait on F10, only need a BLUE slot occupied for position/groupId (a structural precondition, not piloting/judgment). Retagged all 4 auto-check: - scenarioTroopsFullCycle_v2.lua, scenario_extract_menu.lua, scenario_jtac_crate_pack.lua, scenario_feature_k_jtac_vehicle.lua Also fixed stale header comments (TFC's claimed TRZ zone dependency, feature_k's claimed ground/target-presence checks) that don't match what the code actually does. The pilotActive/pilotPassive -> always ia folder-blanket default (from INTEGRATION-TEST-TAGS) doesn't hold universally; documented a (menu)/(fly) qualifier convention for genuine ia scenarios and applied it to the 4 already confirmed (F-046, F-047, the two L5 menu-visual scenarios). run_scenarios.py now re-injects the full source on a RUNNING verdict instead of failing it outright (previously only run_ia_scenario.py did this) -- makes the newly-auto-check-tagged scenarios actually runnable via --no-ai, and keeps both runners' RUNNING handling consistent. 44/44 python tests green. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… printing CATCH-UP-PILOT-SCENARIOS ticket 03, both found live (David): - scenarioTroopsFullCycle_v2.lua step 7 (destroys 4 targets on a timer, validates the alive JTAC reacquires each one) had no guard against re-entry while its ~50s monitoring window was still running. run_ia_scenario.py re-injects the full source every poll_interval (2s) on a RUNNING verdict -- a second re-injection installed a *second* concurrent destroy/snapshot timer racing the first, corrupting the claim log (F-T7.2 FAIL: only 1 distinct target seen, expected >=2). Added a guard that skips reinstalling the timer if one's already running. Also exposed _SCN_TFC_CLEANUP -- this scenario had no external-reset hook at all, so a FAIL inside check() left _G[STEP_N] stuck re-validating the same stale data on any re-run. - run_ia_scenario.py only printed progress on a verdict *token* change -- a multi-step RUNNING scenario's message advances every step while the token stays RUNNING throughout, so a long-but-healthy step (like TFC's step 7) looked indistinguishable from a hang. Now prints on any message change. All 4 ticket-03 scenarios confirmed PASS live. 45/45 python tests green. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…emature-reinjection
CATCH-UP-PILOT-SCENARIOS ticket 04. Audited each scenario's code before
running (per the ticket 03 mistagging lesson) -- 4 of 5 need no piloting:
- scenario_multigroup_transport.lua -> auto-check. Fully self-contained:
mocks ctld.MenuManager/Unit.getByName with a fake unit, no real player.
- scenario_weight_aggregation.lua -> auto-check. "1 step auto" per header.
- scenario_unpack_jtac_drone.lua -> auto-check. Resolves the helo via
hardcoded Unit.getByName("uh1-1"), not coalition.getPlayers; single
injection with ~13 min of internal timers (needs a long poll timeout).
- scenario_farp_repack.lua -> auto-check, AND fixed a premature-reinjection
bug (same family as TFC step-7, ticket 03): step 2 called fail() outright
if the FARP scene wasn't active yet, but playSceneAtPos (step 1) takes
~15-20s to register it -- a tight 2s re-inject loop false-FAILs. Now
retries (bounded 20x) instead, failing for real only past that.
- scenario_warehouse_cycle.lua -> stays ia (fly): genuine piloting (crate
load, takeoff, FARP deploy, reposition >400m, land).
8 of the original 34 ia scenarios now retagged (22 remain). 45/45 py green.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…bustness CATCH-UP-PILOT-SCENARIOS ticket 04 -- 4/5 auto-check scenarios PASS live (warehouse ia(fly) still pending). Found + fixed live: - scenario_farp_repack.lua: referenced the dead FullGas ctld_test framework (nil, same cause as the 194 relics) -> local getTransport(); and never emitted a terminal verdict (looped 1->2->99->1 forever) -> _done flag so the summary step returns PASS. - scenario_unpack_jtac_drone.lua: V3/V4 asserted "no target" after the scenario's own RED unit was destroyed, but a mission RED (Sol_g-2, 4135m) is in lase range so the drone correctly re-tasks. Rewrote V3/V4 to assert the drone no longer lases the specific destroyed unit (David's option 1). Exposed _SCN_JTACDRONE_INSTR (only printed to the DCS screen before) and had each VERIFY publish there for live CLI progress; same missing-_INSTR gap fixed proactively in p2_fob/p3_csfarp/p4_metal (ticket 05). run_ia_scenario.py robustness (all surfaced by the 13-min drone run): - elapsed [mm:ss] stamp on every line + periodic heartbeat (--heartbeat, default 30s) echoing the last real progress line, not the frozen RESULT. - tolerate transient poll errors (--max-errors, default 5): a single HTTP 504 (DCS Lua thread briefly busy) no longer aborts a long run. 52 py tests green. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…05 to auto-check - Ticket 04 done: 4/5 PASS live; scenario_warehouse_cycle deferred -- needs the Farp_FG_Petit_Helipad (FullGas) mod for its warehouse checks, absent on David's install, so it'd FAIL after ~4 min of flight. Stays ia (fly), revisit when the mod is present. Not a code defect. - Ticket 05 audit: all 5 scenarios (fob_scene, p2/p3/p4, feature_f_recon_farp) were ia by folder default but none check flight state or wait on F10 -- each spawns its own crates/scenes and verifies via internal timers, needing only a BLUE slot. Retagged auto-check. - scenario_fob_scene.lua had the same terminal-verdict bug as farp_repack (step 99 reset to 1 but returned RUNNING -> infinite 1->2->99->1 loop); fixed with a _done flag -> PASS. p4_metal_farp already handles the mod being absent gracefully; feature_f_recon_farp already had a terminal PASS. Only scenario_warehouse_cycle has proven a genuine ia(fly) so far; 13 of the original 34 ia scenarios retagged auto-check across tickets 03-05. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
scenario_p2_fob_parachute FAILed live on `attempt to index global 'ctld_test'` -- the dead FullGas test framework (nil, same cause as the 194 relics). Same refs found + fixed across all 5 ticket-05 scenarios: - p2/p3/p4: removed the standalone ctld_test.cleanup() blanket-reset (each scenario does its own targeted cleanup; the runner resets via _SCN_*_CLEANUP). p4 got an explicit Metal FARP scene pack-cleanup in its place. - fob_scene: replaced ctld_test.getTransport() (2x) with a local getTransport() (first BLUE player), like farp_repack. - feature_f_recon_farp: dropped the nil-guarded ctld_test.getTransport() primary lookup; its BLUE-group scan was already the fallback and is now the sole path. mt16 (ticket 07) and warehouse_cycle (deferred) still carry ctld_test refs -- handled when those tickets come up. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…t15/mt16 Systematic audit of every remaining ia-tagged scenario (tickets 06-07, 16 files read in full via subagent) instead of discovering mistags one flight at a time. Result: the pilotPassive/pilotActive folder-blanket "always ia" default was wrong for all but 3 of the original 34. Retagged auto-check (15): scenario_ai_attack_enemy, ai_goto_wpz, ai_transport_visual, ai_troops, feature_i_attack_enemy, feature_i_goto_wpz, mt07..mt15. None gate on the player's inAir or wait on F10 -- they drive an AI helicopter + timers; the slot is used only for position/country. Required mission content (AI helis heliai_*, zones AIZ_*/WPZ_mt10_B) confirmed present in Test_CTLDNEXT_01.miz via exec_lua. Fixes: - mt15: hard-coded slot name "Batumi_UH-1H_0-1" (one specific map) at 3 sites -> resolve first BLUE player dynamically via local getTransport(). - mt16: dead ctld_test.cleanup()/getTransport() -> local getTransport(); file/ID header mismatch corrected; stays ia (menu) -- genuinely interactive (F10 unpack + visual) with no terminal PASS, and redundant with the auto-tier scenario_farp_countryside_spawn.lua. Final tally of the original 34 ia: 31 auto-check, 3 genuine ia (the 2 menu- visual ia(fly), both already PASS; warehouse_cycle deferred on a missing mod; mt16 ia(menu), optional). Real remaining pilot burden ~= 0 -- everything else runs headless with the player just parked in a slot. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…rom --no-ai) Live run of MT-14 revealed the AI-battery scenarios aren't fast auto-check: they wait on an AI helicopter (heliai_*) physically flying a multi-waypoint route to a pickup/dropoff zone -- minutes of real flight per scenario. In the 2s-reinject --no-ai sweep that spams the screen and stalls the whole batch on one scenario (looked "stuck"; the heli was en route at 46 m/s). New tier `auto-slow`: no human/pilot, but excluded from the fast --no-ai sweep; run explicitly with `--tier auto-slow --poll-timeout 900`. Retagged the 9 AI-flight scenarios (scenario_ai_troops + mt07..mt14) auto-check -> auto-slow. scenario_ai_transport_visual stays auto-check (it simulates the land via onAILand, no real flight); ai_attack_enemy/ai_goto_wpz/feature_i_* stay auto-check (spawn own units, timer-driven). Their core logic is already covered fast/headless by the noPlayer aiTransport_featureT/U tests (F-176..182), so auto-slow is the optional heavy end-to-end complement. Final: 22 auto-check, 9 auto-slow, 4 ia (2 ia(fly) menu-visual done, warehouse deferred, mt16 ia(menu) optional). Documented the tier in run_scenarios.py (TIERS/NO_AI_TIERS), README, the integration-testing skill, and recette- procedure.md (EN+FR). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…->180 Live --no-ai sweep sat silently on scenario_unpack_jtac_drone for minutes -- it's auto (no human) but ~13 min of internal VERIFY timers (up to T+795s), too slow for the fast sweep and it stalled the whole batch (looked hung; it was at V3/T+495, 4/4 ok, ~5 min from PASS). Retagged auto-check -> auto-slow alongside the AI-heli battery, and broadened the auto-slow definition to "minutes to resolve: AI flight OR long internal timer chains". Also bumped run_scenarios.py default --poll-timeout 60 -> 180 so the fast --no-ai sweep covers the slowest genuine auto-check scenarios (fob_scene ~130s, p2 ~160s) without a false timeout, and fixed a README example that suggested --poll-timeout 30 (too short). Docs updated (README, skill, recette EN+FR); tier split now 18 auto-check / 10 auto-slow / 4 ia. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…reset-before-each) Root-caused the full-sweep failures: not real bugs, and not "no player" -- the shared CTLD singletons get contaminated across a back-to-back sweep. Observed live: 2 phantom _players entries (uh1h_slot_1/whitelisted from the cl9/cl10 tests) + a wiped MenuManager menu for the real slotted player, so later player-dependent scenarios abort with "no CTLD MenuManager menu". Same class as FIX-LIVE-DCS-FAILURES; a mission reload clears it, but net.load_mission is unavailable on a DCS client (verified), so no Lua reload. Fix: tests/dcs/_reset_state.lua -- prunes phantom players and rebuilds the real players' menus, restoring a clean player/menu baseline without a reload (proven live: pruned=2 rebuilt=1 -> 1 player, hasMenu=true). Wired as run_scenarios.py --reset-before-each (injected before each scenario) and always-on in run_ia_scenario.py. Scope deliberately player/menu only; a deeper need would fall back to a human Shift+R. Also: run_scenario default poll_timeout 60->180 (matches CLI) so the fast sweep covers the slowest auto-check (fob_scene ~130s, p2 ~160s). 55 py tests green. Docs updated (README, skill). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sweep reported "STARTED but no _SCN_<ID>_RESULT variable found" for scenario_ai_attack_enemy / scenario_ai_goto_wpz -- their vars use compound IDs with underscores (_SCN_FI_ATK_RESULT, _SCN_FI_WPZ_RESULT) that the RESULT_VAR_RE / INSTR_VAR_RE / CLEANUP_VAR_RE regexes ([A-Za-z0-9]+) didn't match, so the runner couldn't poll them. Widened all three to [A-Za-z0-9_]+. Regression tests added. Runner bug, not a scenario bug. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…eep FAILs) The full sweep's 3 genuine FAILs were all test-harness artifacts (premature re-injection / missing setup), not CTLD product bugs: - scenario_fob_scene (FOB-SCN): step 2 checks FOB registration, but the scene takes ~120s to build + self-register; the runner re-injects every 2s so step 2 hit at T+2 -> count=0. Step 2 now retries (bounded ~90) instead of a false FAIL, letting the re-inject loop wait the build out. - scenario_feature_i_attack_enemy (FI-ATK): step 2 checks the AI unit moved, but the post-spawn attack task needs ~8s to get it going (step 1 even says "re-inject in 8s+"). Step 2 now retries (bounded 15) until it moves. - scenario_feature_f_recon_farp (FARP): step 3 required a separate tests/dcs/util/inject_red_fob.lua to be injected first (an automated sweep never does). Inlined a mock RED FOB in step 3 (mirrors the already-mocked RED FARP airbase) + removed it at teardown -> self-contained. Header updated. Root cause of these is the same as the ABORTs: scenarios were authored for manual, human-paced re-injection, not a 2s automated loop. 57 py tests green. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The sole full-sweep FAIL (scenarioTroopsFullCycle_v2 step-7 "only 1 distinct target reacquired", passed in isolation) traced to leftover JTAC state: the soft-reset only cleared player/menu, and TFC skipped its cleanup on failure, leaving a registered JTAC + claimed target (live: JTAC-189) that skewed the next run's deconfliction count. - _reset_state.lua now also deregisters all JTACs + clears _claimedTargets before each scenario (safe: JTACs are runtime-created, never mission-defined; every JTAC scenario registers its own afresh). Proven live: jtacsCleared=1 -> JTACs=0 claims=0. - scenarioTroopsFullCycle_v2 now tears down (cleanupAll + reset step globals + _G[STEP_N]=1) on the failure path too, not just at step 8, so a failed run no longer orphans its JTACs/claims or leaves the step machine mid-cycle. 57 py tests green. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… green Tickets 05/06/07 done, PRD + backlog index updated. Full headless sweep (--no-ai --reset-before-each) passes 66/66; real pilot burden reduced to the 2 menu-visual ia(fly) scenarios (both PASS). Optional remainders documented: auto-slow AI battery (covered by F-176..182), mt16 (redundant), warehouse (mod-blocked), and ticket 08's L6 manual sequences. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Deleted scenario_mt16_countryside_farp.lua: ia(menu), never emitted a PASS
(manual F10-unpack + visual), and redundant with the auto-tier headless
scenario_farp_countryside_spawn.lua which already covers the Countryside
FARP deploy.
- Purged the last real FullGas ctld_test refs from tagged scenarios:
F-176/F-177 (dead `ctld_test = ctld_test or {}` leftover, never used),
scenario_warehouse_cycle (dead ctld_test.cleanup(), scenario does its own).
All 82 tagged scenarios are now free of the dead FullGas framework; the 194
untagged relics remain the CLEANUP-LEGACY-DCS-TESTS lot's scope.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… player Expanded the Integration Testing page (EN + FR) with a per-tier table: the exact command to run each tier and what the player must do (nothing / park in a slot / fly / click F10), plus the full-sweep command, the crash-recovery and progress-feedback notes, and a section explaining the cross-scenario state contamination and --reset-before-each. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…14 quarantine
Translate the integration-test scenarios to English (project convention) and
finish the CATCH-UP-PILOT-SCENARIOS harness work:
- Tier taxonomy renamed to say what it means: `ia` -> `human`, flag `--no-ai`
-> `--headless`, runner `run_ia_scenario.py` -> `run_manual_scenario.py`.
("ia" was misleading: those tiers need a human pilot, not an AI.)
- New `disabled` tier + `default_tiers()`: quarantined scenarios are excluded
from every default sweep, reachable only via `--tier disabled`.
- Quarantine mt08/mt14: code and mission are both correct (Land point verified
inside the pickup zone) but the DCS AI helo won't reliably land on the spot,
so the whole-cycle test never completes. Logic covered by F-176..182.
- Extend `_reset_state.lua` to purge orphan `heliai_*_run` clones (was the
cross-scenario contamination that failed mt10/mt11 in a grouped sweep).
- Drop `scenario_mt07_ai_troops.lua`: buggy duplicate of MT-07 (fatal check
short-circuited the wait branch); coverage assured by `scenario_ai_troops`.
- 60 runner unit tests green; luac clean on all tagged scenarios.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tests/recette.md
- Rename docs/recette-procedure.{md,fr.md} -> docs/integration-testing.{md,fr.md}
("recette" is banned vocabulary; nav label was already "Integration Testing")
and update mkdocs.yml.
- Sync the tier taxonomy in both languages (ia -> human, --no-ai -> --headless,
run_ia_scenario -> run_manual_scenario), document the new `disabled` tier, and
fix the stale mt07/mt16 scenario references.
- Delete tests/recette.md: obsolete FullGas-era coverage doc; its coverage is
fully reproduced by the current VEAF test set (147 IDs in busted CI + 47 by
functional symbol), tracked in CLEANUP-LEGACY-DCS-TESTS.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Sorry @davidp57, your pull request is larger than the review limit of 150000 diff characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes
Finalizes CATCH-UP-PILOT-SCENARIOS: the never-run
pilotPassive/pilotActivescenarios have been executed, the harness hardened, and the test taxonomy made honest.
ia→human, flag--no-ai→--headless, runnerrun_ia_scenario.py→run_manual_scenario.py. ("ia" implied AIbut those tiers need a human pilot.)
disabledtier (default_tiers()): quarantined scenarios never run in a defaultsweep, reachable only via
--tier disabled.pickup zone), but the DCS AI helo won't reliably land on the spot → whole-cycle test never
completes. Logic coverage assured by
noPlayerF-176..182 + sibling scenarios._reset_state.luaextended to purge orphanheliai_*_runclones (the contaminationthat failed mt10/mt11 in a grouped sweep — they pass in isolation).
scenario_mt07_ai_troops.lua(buggy duplicate of MT-07).recette-procedure→integration-testing(EN+FR, "recette" is banned) + deletedobsolete
tests/recette.md.Checklist
CTLD.luastays pure Lua 5.1CTLD.luarebuilt ifsrc/changed — N/A, nosrc/change (tests/tooling/docs only)DefaultTiersTests); 60 greenluacheckclean — N/A, nosrc/change;luac -pclean on all tagged scenariosCHANGELOG.md[Unreleased]— N/A, no deliverable (CTLD.lua) behavior changedisabledtier)Notes
noPlayer/F-*,U-*) still carryFrench + banned "recette" — they belong to the separate
CLEANUP-LEGACY-DCS-TESTSlot andwere deliberately left untouched. A coverage audit confirms their coverage is fully
reproduced (147 by ID in busted CI + 47 by functional symbol), so they are deletable after
FullGas validation.
heliai_vehicle/heliai_mt14inTest_CTLDNEXT_01.mizto clearer terrain to un-quarantine mt08/mt14.🤖 Generated with Claude Code